#ifndef ELFREADER_H
#define ELFREADER_H

typedef u32 Elf32_Addr;
typedef u16 Elf32_Half;
typedef u32 Elf32_Off;
typedef u32 Elf32_Word;

/* ELF file header */
typedef struct
{
    char e_ident[16];
    Elf32_Half    e_type;
    Elf32_Half    e_machine;
    Elf32_Word    e_version;
    Elf32_Addr    e_entry;
    Elf32_Off     e_phoff;
    Elf32_Off     e_shoff;
    Elf32_Word    e_flags;
    Elf32_Half    e_ehsize;
    Elf32_Half    e_phentsize;
    Elf32_Half    e_phnum;
    Elf32_Half    e_shentsize;
    Elf32_Half    e_shnum;
    Elf32_Half    e_shstrndx;
} Elf32_Ehdr;

/* Section header */
typedef struct
{
    Elf32_Word sh_name;
    Elf32_Word sh_type;
    Elf32_Word sh_flags;
    Elf32_Addr sh_addr;
    Elf32_Off  sh_offset;
    Elf32_Word sh_size;
    Elf32_Word sh_link;
    Elf32_Word sh_info;
    Elf32_Word sh_addralign;
    Elf32_Word sh_entsize;
} Elf32_Shdr;

/* Segment header */
typedef struct
{
    Elf32_Word p_type;
    Elf32_Off  p_offset;
    Elf32_Addr p_vaddr;
    Elf32_Addr p_paddr;
    Elf32_Word p_filesz;
    Elf32_Word p_memsz;
    Elf32_Word p_flags;
    Elf32_Word p_align;
} Elf32_Phdr;

typedef s32 SectionID;

typedef struct
{
    Elf32_Addr r_offset;
    Elf32_Word r_info;
} Elf32_Rel;

typedef struct
{
    Elf32_Word    st_name;
    Elf32_Addr    st_value;
    Elf32_Word    st_size;
    u8 st_info;
    u8 st_other;
    Elf32_Half    st_shndx;
} Elf32_Sym;

typedef struct
{
    char *base;
    u32 vaddr;
    u8 isPrx;
    u32 maxVaddr;
    Elf32_Ehdr header;
    Elf32_Phdr *segments;
    Elf32_Shdr *sections;
} ElfReader;

ElfReader elfr_init(void *ptr);
void elfr_load(ElfReader *reader, u32 vaddr);
const char *elfr_getSectName(ElfReader *reader, s32 section);
SectionID elfr_getSectByName(ElfReader *reader, const char *name);

#endif

